package com.ychp.web.interceptor;

import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ychp.common.model.Response;
import com.ychp.user.model.User;
import com.ychp.user.service.UserReadService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Desc:
 * Author: <a href="ychp@terminus.io">应程鹏</a>
 * Date: 16/7/30
 */
@Slf4j
public class LoginInterceptor extends HandlerInterceptorAdapter {

    private final static String URL_ENCODER_CODE = "UTF-8";

    private Map<String,List<String>> whiteList;

    private UserReadService userReadService;

    public LoginInterceptor(UserReadService userReadService){
        super();
        this.userReadService = userReadService;
        whiteList = Maps.newHashMap();
        List<String> urls;
        BufferedReader br = null;
        String[] values;
        String url;
        InputStream is = this.getClass().getResourceAsStream("/auth/white_list");
        try {
            br = new BufferedReader(new InputStreamReader(is));
            for(String line = br.readLine(); line!=null; line = br.readLine()){
                if(StringUtils.isEmpty(line) || line.trim().startsWith("#")){
                    continue;
                }
                values = line.split(":");
                url = values[0].trim();
                for(String method : values[1].split(",")){
                    method = method.toUpperCase();
                    urls = whiteList.get(method);
                    if(urls == null){
                        urls = Lists.newArrayList();
                    }
                    urls.add(url);
                    whiteList.put(method, urls);
                }
            }
        } catch (FileNotFoundException e) {
            log.error("white list file not exist");
        } catch (IOException e) {
            log.error("white list read fail, error = {}", Throwables.getStackTraceAsString(e));
        } finally{
            if(br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    log.error("close bufferedReader fail, error = {}", Throwables.getStackTraceAsString(e));
                }
            }
        }
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        String method = request.getMethod().toUpperCase();
        List<String> urls;
        urls = whiteList.get(method);
        if(urls != null){
            for(String item : urls){
                if(uri.matches(item)){
                    return true;
                }
            }
        }
        HttpSession session = request.getSession();
        User user = (User)session.getAttribute("online");

        Cookie[] cookies = request.getCookies();
        String token = null;
        Cookie cookie = null;
        if(cookies != null) {
            for (Cookie item : cookies) {
                cookie = item;
                if (Objects.equals(cookie.getName(), "msid")) {
                    token = cookie.getValue();
                }
            }
        }
        if(user == null && !StringUtils.isEmpty(token)){
            Response userR = userReadService.findBy(token);
            if(userR.isSuccess()){
                session.setAttribute("online", userR.getResult());
                user = (User) userR.getResult();
                cookie.setMaxAge(7200000);
                cookie.setPath("/");
                response.addCookie(cookie);
            }else{
                cookie.setValue("");
                cookie.setMaxAge(0);
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }

        if(user == null) {
            response.sendRedirect("/login?target=" + URLEncoder.encode(uri, URL_ENCODER_CODE));
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }
}
